#include	"../core/mongoose.h"
#include	"api_def.h"
#include	<algorithm>
#include	<random>

static int Api_MD5(lua_State * pL) {
	size_t nLen;
	const char * pData = lua_tolstring(pL, 1, &nLen);
	char pBuf[33] = { 0 };
	unsigned char pDig[16] = { 0 };

	MD5_CTX iCtx;
	MD5_Init(&iCtx);
	MD5_Update(&iCtx, (const unsigned char *)pData, nLen);
	MD5_Final(pDig, &iCtx);

	cs_to_hex(pBuf, pDig, sizeof(pDig));
	lua_pushstring(pL, pBuf);
	return 1;
}

static int Api_Base64Encode(lua_State * pL) {
	size_t nSrc, nDst;
	const char * pData = lua_tolstring(pL, 1, &nSrc);
	nDst = nSrc * 4 / 3 + 3;
	char * pDst = new char[nDst];
	memset(pDst, 0, nDst);
	mg_base64_encode((const unsigned char *)pData, nSrc, pDst);
	lua_pushstring(pL, pDst);
	delete[] pDst;
	return 1;
}

static int Api_Base64Decode(lua_State * pL) {
	size_t nSrc, nDst;
	const char * pData = lua_tolstring(pL, 1, &nSrc);
	nDst = nSrc * 3 / 4 + 1;
	char * pDst = new char[nDst];
	memset(pDst, 0, nDst);
	mg_base64_decode((const unsigned char *)pData, nSrc, pDst);
	lua_pushstring(pL, pDst);
	delete[] pDst;
	return 1;
}

static int Api_UrlDecode(lua_State * pL) {
	size_t nSrc;
	const char * pData = lua_tolstring(pL, 1, &nSrc);
	char * pDst = new char[nSrc + 1];
	memset(pDst, 0, nSrc + 1);
	mg_url_decode(pData, nSrc, pDst, nSrc + 1, true);
	lua_pushstring(pL, pDst);
	delete[] pDst;
	return 1;
}

#if defined(max)
#undef max
#endif

#if defined(min)
#undef min
#endif

static int Api_Random(lua_State * pL) {
	std::random_device iRand;
	double nRet = iRand() * 1.0 / (iRand.max() - iRand.min());

	int nTop = lua_gettop(pL);
	if (nTop == 0) {
		lua_pushnumber(pL, (lua_Number)nRet);
	} else if (nTop == 1) {
		lua_pushnumber(pL, (lua_Number)(nRet * lua_tonumber(pL, 1)));
	} else {
		double nMin = lua_tonumber(pL, 1);
		double nMax = lua_tonumber(pL, 2);
		nRet = nRet * (std::abs(nMax - nMin)) + std::min(nMin, nMax);
		lua_pushnumber(pL, (lua_Number)nRet);
	}

	return 1;
}

void RegisterApi_Utils(lua_State * pL) {
	REGAPI(pL, Api_MD5, "md5");
	REGAPI(pL, Api_Base64Encode, "base64_encode");
	REGAPI(pL, Api_Base64Decode, "base64_decode");
	REGAPI(pL, Api_UrlDecode, "url_decode");
	REGAPI(pL, Api_Random, "random");
}